import { RequestInter, DefaultParamsInter } from '@/types/reqeust';

export default class MyRequest {
	/** 默认参数 */
	default: DefaultParamsInter = {
		method: 'GET',
	};

	/** 配置拦截器 */
	interface = {
		reqeust: (...args: any[]) => args,
		response: (...args: any[]) => args,
	};

	constructor(options?: DefaultParamsInter) {
		this.default = { ...this.default, ...options };
	}

	/**
	 * 函数“request”使用提供的选项发送请求，并返回一个 Promise，该 Promise 会使用响应数据进行解析或因错误而拒绝。
	 * @param {RequestInter} options -
	 * “request”函数中的“options”参数似乎是一个包含有关要发出的请求的信息的对象。它可能包括“url”、“method”、“headers”、“data”等属性，这些属性是使用“uni.request”方法发出
	 * HTTP 请求所必需的
	 * @returns 从“request”函数返回一个 Promise。
	 */
	request(options: RequestInter): Promise<{ [key: string]: any }> {
		const params = this.disposeParams(options);
		const config = this.interface.reqeust(params);

		// 实现加载提示(500ms内完成请求不提示Loading)
		let timer = setTimeout(() => {
			uni.showLoading({
				title: '加载中',
				mask: true,
			});
		}, 500);

		return new Promise((resolve: Function, reject: Function) => {
			uni.request({
				...config,
				success: (res: RequestSuccessCallbackResult) => {
					// 响应拦截必须返回
					const result = this.interface.response(res);
					if (!result) {
						reject('响应拦截必须return值');
						return;
					}

					resolve(result);
				},
				fail: (error: GeneralCallbackResult) => {
					console.log(`请求${options.url}时出错了:`, error);
					// 处理请求超时
					if (error.errMsg?.indexOf('-1 timeout')) {
						uni.showToast({
							title: '连接服务器超时',
							duration: 2000,
							icon: 'none',
							position: 'bottom',
						} as object);
					}
					reject(error);
				},
				complete(res: any) {
					clearTimeout(timer);
					uni.hideLoading();

					if (res.statusCode === 404) {
						// 定时器解决 showToast 与 Loading 冲突
						setTimeout(() => {
							uni.showToast({
								title: '连接服务器失败',
								duration: 2000,
								icon: 'none',
								position: 'bottom',
								success() {
									console.log('弹框');
								},
								fail(err: Error) {
									console.log('失败', err);
								},
							} as object);
						});
					}
				},
			});
		});
	}

	/**
	 * 函数“disposeParams”合并 TypeScript 应用程序的默认和提供的请求参数，包括 URL 和标头。
	 * @param {RequestInter} options - 请求间
	 * @returns
	 * 函数“disposeParams”返回一个对象，其中包含来自“this.default”和“options”的属性。它还将“baseURL”与“options”中的“url”连接起来，将“Content-Type”标头设置为“application/json”，并合并“this.default”和“options.headers”中的标头。
	 */
	disposeParams(options: RequestInter): object {
		const { baseURL } = this.default;

		return {
			...this.default,
			...options,
			url: baseURL ? baseURL + options.url : options.url,
			header: {
				'Content-Type': 'application/json',
				...this.default.headers,
				...options.headers,
			},
		};
	}
}
